package com.atguigu.gmall.activity.service.impl;

import com.atguigu.gmall.activity.mapper.ActivityInfoMapper;
import com.atguigu.gmall.activity.mapper.ActivityRuleMapper;
import com.atguigu.gmall.activity.mapper.ActivitySkuMapper;
import com.atguigu.gmall.activity.mapper.CouponInfoMapper;
import com.atguigu.gmall.activity.service.ActivityInfoService;
import com.atguigu.gmall.model.activity.*;
import com.atguigu.gmall.model.cart.CarInfoVo;
import com.atguigu.gmall.model.cart.CartInfo;
import com.atguigu.gmall.model.enums.ActivityType;
import com.atguigu.gmall.model.order.OrderDetail;
import com.atguigu.gmall.model.product.SkuInfo;
import com.atguigu.gmall.product.client.ProductFeignClient;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

import static java.util.stream.Collectors.toList;

/**
 * @author mqx
 * @date 2020-12-1 16:26:02
 */
@Service
public class ActivityInfoServiceImpl extends ServiceImpl<ActivityInfoMapper, ActivityInfo> implements ActivityInfoService {

    @Autowired
    private ActivityInfoMapper activityInfoMapper;

    @Autowired
    private ActivityRuleMapper activityRuleMapper;

    @Autowired
    private ActivitySkuMapper activitySkuMapper;

    @Autowired
    private ProductFeignClient productFeignClient;

    @Autowired
    private CouponInfoMapper couponInfoMapper;

    @Override
    public IPage<ActivityInfo> selectPage(Page<ActivityInfo> pageParam) {
        QueryWrapper<ActivityInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.orderByDesc("id");

        IPage<ActivityInfo> infoIPage = activityInfoMapper.selectPage(pageParam, queryWrapper);
        //  获取到活动类型-并赋值给ActivityTypeString
        infoIPage.getRecords().stream().forEach(item->{
            item.setActivityTypeString(ActivityType.getNameByType(item.getActivityType()));
        });
        return infoIPage;
    }

    @Override
    public List<SkuInfo> findSkuInfoByKeyword(String keyword) {
        //  根据关键词查询所有的skuInfo列表
        List<SkuInfo> skuInfoList = productFeignClient.findSkuInfoByKeyword(keyword);
        //  获取当前列表的skuId 组成一个新的集合。
        List<Long> skuIdList = skuInfoList.stream().map(SkuInfo::getId).collect(toList());

        //  获取当前活动列表的skuId
        List<Long> existSkuIdList = activityInfoMapper.selectExistSkuIdList(skuIdList);
        //  通过skuId 获取到当前对象的集合
        List<SkuInfo> skuInfos = existSkuIdList.stream().map(skuid -> productFeignClient.getSkuInfo(skuid)).collect(toList());
        skuInfoList.removeAll(skuInfos);
        //  skuIdList
        return skuInfoList;
    }



    @Transactional(rollbackFor = Exception.class)
    @Override
    public void saveActivityRule(ActivityRuleVo activityRuleVo) {
        //  根据活动Id先删除活动规则
        activityRuleMapper.delete(new QueryWrapper<ActivityRule>().eq("activity_id",activityRuleVo.getActivityId()));
        //  根据活动Id先删除活动的商品
        activitySkuMapper.delete(new QueryWrapper<ActivitySku>().eq("activity_id",activityRuleVo.getActivityId()));

        List<ActivityRule> activityRuleList = activityRuleVo.getActivityRuleList();
        List<ActivitySku> activitySkuList = activityRuleVo.getActivitySkuList();
        // 后续处理
        List<Long> couponIdList = activityRuleVo.getCouponIdList();
        if(!CollectionUtils.isEmpty(couponIdList)) {
            //更新优惠券
            CouponInfo couponInfo = new CouponInfo();
            couponInfo.setActivityId(0L);
            couponInfoMapper.update(couponInfo,new QueryWrapper<CouponInfo>().eq("activity_id",activityRuleVo.getActivityId()));
        }

        for(ActivityRule activityRule : activityRuleList) {
            activityRule.setActivityId(activityRuleVo.getActivityId());
            activityRuleMapper.insert(activityRule);
        }

        for(ActivitySku activitySku : activitySkuList) {
            activitySku.setActivityId(activityRuleVo.getActivityId());
            activitySkuMapper.insert(activitySku);
        }

        if(!CollectionUtils.isEmpty(couponIdList)) {
            for(Long couponId : couponIdList) {
                CouponInfo couponInfoUp = couponInfoMapper.selectById(couponId);
                couponInfoUp.setActivityId(activityRuleVo.getActivityId());
                couponInfoMapper.updateById(couponInfoUp);
            }
        }
    }

    @Override
    public Map<String, Object> findActivityRuleList(Long activityId) {
        Map<String, Object> result = new HashMap<>();

        QueryWrapper queryWrapper = new QueryWrapper<ActivityRule>();
        queryWrapper.eq("activity_id",activityId);
        List<ActivityRule> activityRuleList = activityRuleMapper.selectList(queryWrapper);
        result.put("activityRuleList", activityRuleList);

        QueryWrapper activitySkuQueryWrapper = new QueryWrapper<ActivitySku>();
        activitySkuQueryWrapper.eq("activity_id",activityId);
        List<ActivitySku> activitySkuList = activitySkuMapper.selectList(activitySkuQueryWrapper);
        List<Long> skuIdList = activitySkuList.stream().map(ActivitySku::getSkuId).collect(Collectors.toList());
        List<SkuInfo> skuInfoList = productFeignClient.findSkuInfoBySkuIdList(skuIdList);

        //优惠券信息
        QueryWrapper couponInfoQueryWrapper = new QueryWrapper<CouponInfo>();
        couponInfoQueryWrapper.eq("activity_id",activityId);
        List<CouponInfo> couponInfoList = couponInfoMapper.selectList(activitySkuQueryWrapper);
        result.put("couponInfoList", couponInfoList);

        result.put("skuInfoList", skuInfoList);

        return result;
    }


    @Override
    public List<ActivityRule> findActivityRule(Long skuId) {
        return activityInfoMapper.selectActivityRuleList(skuId);
    }

    @Override
    public List<CarInfoVo> findCartActivityRuleMap(List<CartInfo> cartInfoList, Map<Long, Long> skuIdToActivityIdMap) {
        //  声明一个对象集合来存储数据
        List<CarInfoVo> carInfoVoList = new ArrayList<>();

        //  将 skuId 转换为一个集合
        List<Long> skuIdList = cartInfoList.stream().map(CartInfo::getSkuId).collect(toList());

        //  根据 skuId 列表，查询活动的规则
        List<ActivityRule> activityRuleList = activityInfoMapper.selectCartActivityRuleList(skuIdList);

        //以skuId分组，获取skuId对应的活动规则   1000 100 2000 200 5000 1000
        //  key = skuId value = List<ActivityRule>
        Map<Long, List<ActivityRule>> skuIdToActivityRuleListMap = activityRuleList.stream().collect(Collectors.groupingBy(activityRule -> activityRule.getSkuId()));

        //  活动Id分组，获取活动Id对应的sku
        //  因为在活动规则中，如果多个商品属于同一个活动，则会自动选择当前的促销规则。
        Map<Long, List<ActivityRule>> activityIdToActivityRuleListAllMap = activityRuleList.stream().collect(Collectors.groupingBy(activityRule -> activityRule.getActivityId()));

        //  对应 skuId 所对应的cartInfo 存储到一个map集合中
        Map<Long, CartInfo> skuIdToCartInfoMap = new HashMap<>();
        for (CartInfo cartInfo : cartInfoList) {
            skuIdToCartInfoMap.put(cartInfo.getSkuId(),cartInfo);
        }
        //  循环遍历
        Iterator<Map.Entry<Long, List<ActivityRule>>> iterator = activityIdToActivityRuleListAllMap.entrySet().iterator();
        //  一个活动的所有购物车对象
        while (iterator.hasNext()){
            Map.Entry<Long, List<ActivityRule>> entry = iterator.next();
            Long activityId = entry.getKey();
            //  获取活动id 对应的sku集合

            List<ActivityRule> currentActivityRuleList = entry.getValue();
            //  活动id对应的购物车skuId列表，即activitySkuIdSet列表可以组合使用活动规则
            //  目的： 30 ，31 ，32  并不是skuIdList因为它里面可能存在很多个skuId ，有的skuId 并不是在活动范围中 一个活动下对应的skuId .
            Set<Long> activitySkuIdSet = currentActivityRuleList.stream().map(ActivityRule::getSkuId).collect(Collectors.toSet());
            //  创建对象
            CarInfoVo carInfoVo = new CarInfoVo();
            //  存储当前 CarInfoVo 中 cartInfoList属性赋值
            List<CartInfo> curentCartInfoList = new ArrayList<>();
            for(Long skuId : activitySkuIdSet) {
                skuIdToActivityIdMap.put(skuId, activityId);
                //                for (CartInfo cartInfo : cartInfoList) {
                //                    if (cartInfo.getSkuId().equals(skuId)){
                //                        curentCartInfoList.add(cartInfo);
                //                    }
                //                }
                curentCartInfoList.add(skuIdToCartInfoMap.get(skuId));
            }
            carInfoVo.setCartInfoList(curentCartInfoList);
            //  获取该活动的规则 同一个活动下的购物项规则都是一样的.
            List<ActivityRule> skuActivityRuleList = skuIdToActivityRuleListMap.get(activitySkuIdSet.iterator().next());
            carInfoVo.setActivityRuleList(skuActivityRuleList);
            carInfoVoList.add(carInfoVo);
        }

        return carInfoVoList;
    }

    //  计算金额客户端传递有可能出现造假，所以后台必须重新计算一次。
    @Override
    public Map<Long, ActivityRule> findTradeActivityRuleMap(List<OrderDetail> orderDetailList) {
        //购物项activityId对应的最优活动规则
        Map<Long, ActivityRule> activityIdToActivityRuleMap = new HashMap<>();

        //获取skuId对应的购物项
        Map<Long, OrderDetail> skuIdToOrderDetailMap = new HashMap<>();
        for(OrderDetail orderDetail : orderDetailList) {
            skuIdToOrderDetailMap.put(orderDetail.getSkuId(), orderDetail);
        }
        //  获取skuId 列表
        List<Long> skuIdList = orderDetailList.stream().map(OrderDetail::getSkuId).collect(Collectors.toList());
        //  查询skuId 对应的活动规则
        List<ActivityRule> activityRuleList = activityInfoMapper.selectCartActivityRuleList(skuIdList);
        //skuId分组，获取skuId对应的活动规则
        Map<Long, List<ActivityRule>> skuIdToActivityRuleListMap = activityRuleList.stream().collect(Collectors.groupingBy(activityRule -> activityRule.getSkuId()));
        //活动Id分组，获取活动Id对应的sku
        Map<Long, List<ActivityRule>> activityIdToActivityRuleListMap = activityRuleList.stream().collect(Collectors.groupingBy(activityRule -> activityRule.getActivityId()));

        Iterator<Map.Entry<Long, List<ActivityRule>>> iterator = activityIdToActivityRuleListMap.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<Long, List<ActivityRule>> entry = iterator.next();
            //  Long activityId = entry.getKey();
            List<ActivityRule> currentActivityRuleList = entry.getValue();
            // 活动id对应的购物车skuId列表。
            Set<Long> activitySkuIdSet = currentActivityRuleList.stream().map(ActivityRule::getSkuId).collect(Collectors.toSet());
            // 该活动的总金额 {如果是满减打折则使用activityTotalAmount}
            BigDecimal activityTotalAmount = new BigDecimal("0");
            // 该活动订单明细的个数{如果是满件打折的时候，需要判断activityTotalNum}
            Integer activityTotalNum = 0;
            for (Long skuId : activitySkuIdSet) {
                //  获取当前sku对应的活动id
                OrderDetail orderDetail = skuIdToOrderDetailMap.get(skuId);
                //  订单明细的总金额
                BigDecimal skuTotalAmount = orderDetail.getOrderPrice().multiply(new BigDecimal(orderDetail.getSkuNum()));
                //  计算这个活动的总金额
                activityTotalAmount = activityTotalAmount.add(skuTotalAmount);
                activityTotalNum += orderDetail.getSkuNum();

            }
            // 获取skuId 对应的该活动规则
            Long skuId = activitySkuIdSet.iterator().next();
            List<ActivityRule> skuActivityRuleList = skuIdToActivityRuleListMap.get(skuId);
            for (ActivityRule activityRule : skuActivityRuleList) {
                //  数据库存储的 FULL_REDUCTION
                if (activityRule.getActivityType().equals(ActivityType.FULL_REDUCTION.name())) {
                    //  活动总金额大于活动规则的总金额
                    if (activityTotalAmount.compareTo(activityRule.getConditionAmount()) > -1) {
                        //  设置优惠后见减少的金额
                        activityRule.setReduceAmount(activityRule.getBenefitAmount());
                        //  设置好skuId 列表
                        activityRule.setSkuIdList(new ArrayList<>(activitySkuIdSet));
                        //  活动Id对应的最优规则
                        activityIdToActivityRuleMap.put(activityRule.getActivityId(), activityRule);
                        break;
                    }
                } else {
                    //  如果订单项购买个数大于等于满减件数，则优化打折 FULL_DISCOUNT
                    if (activityTotalNum.intValue() >= activityRule.getConditionNum()) {
                        //  9折  9/10 = 0.9  totalAmount *0.9
                        BigDecimal skuDiscountTotalAmount = activityTotalAmount.multiply(activityRule.getBenefitDiscount().divide(new BigDecimal("10")));
                        //  activityTotalAmount-skuDiscountTotalAmount
                        BigDecimal reduceAmount = activityTotalAmount.subtract(skuDiscountTotalAmount);
                        //  设置优惠后的金额reduceAmount
                        activityRule.setReduceAmount(reduceAmount);
                        activityRule.setSkuIdList(new ArrayList<>(activitySkuIdSet));
                        activityIdToActivityRuleMap.put(activityRule.getActivityId(), activityRule);
                        break;
                    }
                }
            }
        }
        return activityIdToActivityRuleMap;
    }
}
